import numpy as np
import math
import json
import os
import cv2
from collections import OrderedDict
import pandas as pd
from tqdm import tqdm
def distance(p0, p1):
    """
    计算二维点间的距离
    """
    drawer = []
    drawer.append({'line': [p0, p1]})
    return (np.linalg.norm(np.asarray(p1) - np.asarray(p0)))
def cross_point(p, ls, le):
    try:
        k = (le[1] - ls[1]) / (le[0] - ls[0])
        A = np.asarray([[k, -1], [1.0 / k, 1]])
        b = np.asarray([k * ls[0] - ls[1], p[0] / k + p[1]])
        return np.linalg.solve(A, b)
    except ZeroDivisionError:
        return np.asanyarray([ls[0], p[1]])
    
def distance_point_to_line(p, ls, le):
    """
    计算点p到直线ls_le的距离,二维
    """
    return distance(p, cross_point(p, ls, le))


def vector_norm(data, axis=None, out=None):
    data = np.array(data, dtype=np.float64, copy=True)
    if out is None:
        if data.ndim == 1:
            return np.sqrt(np.dot(data, data))
        data *= data
        out = np.atleast_1d(np.sum(data, axis=axis))
        np.sqrt(out, out)
        return out
    else:
        data *= data
        np.sum(data, axis=axis, out=out)
        np.sqrt(out, out)

def angle_between_vectors(v0, v1, directed=True, axis=0):
    v0 = np.array(v0, dtype=np.float64, copy=False)
    v1 = np.array(v1, dtype=np.float64, copy=False)
    dot = np.sum(v0 * v1, axis=axis)
    dot /= vector_norm(v0, axis=axis) * vector_norm(v1, axis=axis)
    return np.arccos(dot if directed else np.fabs(dot))
def min_angle_between_vector_and_horizontal_line(vs, ve):
    """
    计算向量与水平向量的最小夹角
    """
    v = np.asarray(ve) - np.asarray(vs)
    vh = np.asarray([ve[0], vs[1]]) - np.asarray(vs)
    return np.rad2deg(angle_between_vectors(v, vh))



def calculate(height,width,point_list,spacing):
    point_list = [[int(p[0]),int(p[1])] for p in point_list]
    # height,width = image.shape[:-1]
    ## 获取的坐标为yx格式
    ## 肺尖
    A2 = point_list[21]
    A1 = point_list[20]
    ## 肋膈角
    B2 = point_list[23]
    B1 = point_list[22]
    ## 左侧肋骨
    E1 = point_list[8]
    E2 = point_list[9]
    E3 = point_list[10]
    E4 = point_list[11]
    ## 右侧肋骨
    D1 = point_list[4]
    D2 = point_list[5]
    D3 = point_list[6]
    D4 = point_list[7]
    ## 胸椎棘突
    H1 = point_list[0]
    H2 = point_list[1]
    H3 = point_list[2]
    H4 = point_list[3]
    ## 锁骨
    G1 = point_list[12]
    G2 = point_list[13]
    G3 = point_list[14]
    G4 = point_list[15]
    F1 = point_list[16]
    F2 = point_list[17]
    F3 = point_list[18]
    F4 = point_list[19]
    
    # print(F1,F2,F3,F4,G1,G2,G3,G4)
    F5 = [(F1[0]+F2[0])//2,(F1[1]+F2[1])//2]
    F6 = [(F3[0]+F4[0])//2,(F3[1]+F4[1])//2]
    G5 = [(G1[0] + G2[0]) // 2, (G1[1] + G2[1]) // 2]
    G6 = [(G3[0] + G4[0]) // 2, (G3[1] + G4[1]) // 2]
    # 肺尖
    # print(A1,A2)
    def a3():
        return A1[0] * spacing
    def a4():
        return A2[0] * spacing
    # 肋隔角
    def b3():
        return (height - B1[0]) * spacing
    def b4():
        return (height - B2[0]) * spacing

    # # 左右胸壁
    # def c1():
    #     return (np.where(image[B1[0],:,0] > 5)[0].min()) * spacing
    # def c2():
    #     return (width - np.where(image[B2[0],:,0] > 5)[0].max()) * spacing
    #
    #
    # # 摄影区
    # def S3_S2():
    #     return (image[:,:,0]>5).astype(np.float).sum() / (width*height)


    # 左右对称
    def a1_a2():
        a1 = A1[1]
        a2 = width - A2[1]
        # return abs(a1-a2) * spacing
        return a1 * spacing,a2 * spacing
    def b1_b2():
        b1 = B1[1]
        b2 = width - B2[1]
        # return abs(b1 - b2) * spacing
        return b1 * spacing,b2 * spacing
    def d1_e1():
        d1 = D1[1]
        e1 = width - E1[1]
        # return abs(d1-e1) * spacing
        return d1 * spacing,e1 * spacing
    def d2_e2():
        d2 = D2[1]
        e2 = width - E2[1]
        # return abs(d2-e2) * spacing
        return d2 * spacing,e2 * spacing
    def d3_e3():
        d3 = D3[1]
        e3 = width - E3[1]
        # return abs(d3-e3) * spacing
        return d3 * spacing,e3 * spacing
    def d4_e4():
        d4 = D4[1]
        e4 = width - E4[1]
        # return abs(d4-e4) * spacing
        return  d4 * spacing,e4 * spacing
    def a3_b3():
        a3 = A1[0]
        b3 = height-B1[0]
        # return abs(a3-b3) * spacing
        return a3 * spacing,b3 * spacing
    def a4_b4():
        a4 = A1[0]
        b4 = height-B2[0]
        # return abs(a4-b4) * spacing
        return a4 * spacing,b4 * spacing
    ## 胸廓、胸锁关节对称
    def f5():
        return distance_point_to_line(F5[::-1],H1[::-1],H4[::-1]) * spacing
    def g5():
        return distance_point_to_line(G5[::-1],H1[::-1],H4[::-1]) * spacing
    def f3_g3():
        return F3[0] * spacing,G3[0] * spacing
    ## F3和G3与水平线夹角
    def angle_F3_G3():
        return min_angle_between_vector_and_horizontal_line(G3[::-1],F3[::-1])
    ## 锁肩有无耸肩
    def angle_F5_F6():
        return min_angle_between_vector_and_horizontal_line(F5[::-1],F6[::-1])
    def angle_G5_G6():
        return min_angle_between_vector_and_horizontal_line(G5[::-1],G6[::-1])
    def s6():
        ## 肺尖和肋膈角之间的矩形区域面积
        return abs(B2[1]-B1[1])*spacing * abs(min(A1[0],A2[0])-max(B1[0],B2[0]))*spacing
    def s7():
        ##肋膈角往图像底端作垂线，算矩形的面积
        return abs(B2[1]-B1[1])*spacing * abs(min(B1[0],B2[0]))*spacing

    return {'a3':a3(),
            'a4':a4(),
            'b3':b3(),
            'b4':b4(),
            # 'c1':c1(),
            # 'c2':c2(),
            # 'S3_S2':S3_S2(),
            'a1':a1_a2()[0],
            'a2':a1_a2()[1],
            'b1':b1_b2()[0],
            'b2':b1_b2()[1],
            'd1':d1_e1()[0],
            'e1':d1_e1()[1],
            'd2':d2_e2()[0],
            'e2':d2_e2()[1],
            'd3':d3_e3()[0],
            'e3':d3_e3()[1],
            'd4':d4_e4()[0],
            'e4':d4_e4()[1],
            'f5':f5(),
            'g5':g5(),
            'f3':f3_g3()[0],
            'g3':f3_g3()[1],
            'angle_F3_G3':angle_F3_G3(),
            'angle_F5_F6':angle_F5_F6(),
            'angle_G5_G6':angle_G5_G6(),
            'S6':s6(),
            'S7':s7()}
    

if __name__ == '__main__':
    # json_file = json.load(open('label_file/point_0108_train.json')) + json.load(open('label_file/point_0108_val.json'))
    # json_file = json.load(open('label_file/point_0322.json'))
    json_file = json.load((open('label_file/pred.json')))
    # json_file = json.load(open('label_file/calculate_result/pred_val.json')) + json.load(open('label_file/calculate_result/pred_train.json'))
    # spacing_file = json.load(open('label_file/spacing.json'))
    csv_data = pd.DataFrame(columns=['studyInstUid','a3','a4','b3','b4','a1','a2','b1','b2','d1','e1','d2','e2','d3','e3',
                                     'd4','e4','f5','g5','f3','g3','angle_F3_G3','angle_F5_F6','angle_G5_G6','S6','S7'])
    for anno in tqdm(json_file[:]):
        height,width,spacing = anno['info'][0],anno['info'][1],anno['info'][2]
        if spacing > 0.3:
            spacing=0.143
        label = [(p[0])[::-1]for p in anno['point']]
        result = calculate(height,width,label,spacing)
        result['studyInstUid'] = anno['name']
        csv_data = csv_data.append(pd.DataFrame(result,index=[0]))
    csv_data = csv_data[['studyInstUid','a3','a4','b3','b4','a1','a2','b1','b2','d1','e1','d2','e2','d3','e3',
                                     'd4','e4','f5','g5','f3','g3','angle_F3_G3','angle_F5_F6','angle_G5_G6','S6','S7']]
    csv_data.to_csv('label_file/calculate_result/result_pred_0510.csv',index=False)
        # for p in label:
        #     cv2.circle(image, (p[1],p[0]), 3, (0, 128, 255), thickness=10)
        
        # print(result)
        # print('*'*30)
        # cv2.imshow('image with point',cv2.resize(image,(640,768)))
        # cv2.waitKey()
        
        